#! /usr/bin/env python

##    hittest Copyright  (C)  2007 Donn.C.Ingle
##
##    Contact: donn.ingle@gmail.com - I hope this email lasts.
##
##    This program is free software; you can redistribute it and/or modify
##    it under the terms of the GNU General Public License as published by
##    the Free Software Foundation; either version 2 of the License, or
##     ( at your option )  any later version.
##
##    This program is distributed in the hope that it will be useful,
##    but WITHOUT ANY WARRANTY; without even the implied warranty of
##    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
##    GNU General Public License for more details.
##
##    You should have received a copy of the GNU General Public License
##    along with this program; if not, write to the Free Software
##    Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
##

import pygtk
pygtk.require('2.0')
import gtk, gobject, cairo
from gtk import gdk

# Create a GTK+ widget on which we will draw using Cairo
class Screen(gtk.DrawingArea):

    # Draw in response to an expose-event
    __gsignals__ = { "expose-event": "override" }

    def __init__(self):
        super(Screen,self).__init__()
        # gtk.Widget signals
        self.connect("button_press_event", self.button_press)
        self.connect("button_release_event", self.button_release)
        self.connect("motion_notify_event", self.motion_notify)
        # More GTK voodoo : unmask events
        self.add_events(gdk.BUTTON_PRESS_MASK |
                        gdk.BUTTON_RELEASE_MASK |
                        gdk.POINTER_MOTION_MASK)
        self.cr = None

    # Handle the expose-event by drawing
    def do_expose_event(self, event):

        # Create the cairo context
        self.cr = self.window.cairo_create()
        self.hitpath = None #Is set later

        # Restrict Cairo to the exposed area; avoid extra work
        self.cr.rectangle(event.area.x, event.area.y,
                event.area.width, event.area.height)
        self.cr.clip()

        self.draw(self.cr, *self.window.get_size())


    def draw(self, cr, width, height):
	    pass

    def button_press(self,widget,event):
        pass
    def button_release(self,widget,event):
        pass
    def motion_notify(self,widget,event):
        pass

# GTK mumbo-jumbo to show the widget in a window and quit when it's closed
def run(Widget):
    window = gtk.Window()
    window.connect("delete-event", gtk.main_quit)
    widget = Widget()
    widget.show()
    window.add(widget)
    window.present()
    gtk.main()



class Shapes(Screen):

    def __init__(self):
        Screen.__init__(self)
        self.x = self.y = 10
        self.oxx = self.oyy = self.ox = self.oy = 0
        self.drag = False
        self.hit = False
        
    #Override the press event
    def button_press(self,widget,event):

        ## Gues what? Cairo had it built-in all along :)
        ## You just need to keep a ref to the context.
        ## I'm not sure if re-"drawing" the entire path, just so you can
        ## test it for a hit is faster than the other version of this
        ## script that uses a manual python-speed algorithm.
        self.drag = True
        self.cr.append_path(self.hitpath) # re-gen the path
        self.hit = self.cr.in_fill(event.x, event.y) # Test it. Sweet.
        self.oxx = event.x - self.ox
        self.oyy = event.y - self.oy
        print self.hit
        
    def button_release(self,widget,event):
        self.drag = False

    def draw(self, cr, width, height):
        x,y = self.x - self.oxx, self.y - self.oyy
        sx = sy = 50
        cr.move_to(x,y)
        cr.line_to(x+sx,y)
        cr.line_to(x+sx,y+sy)
        cr.line_to(x+(sx/2),y+sy)
        cr.line_to(x+(sx/2),y+(sy/2))
        cr.line_to(x,y+(sy/2))
        cr.line_to(x,y+sy)
        cr.line_to(x-sx,y+sy)
        cr.close_path()
        cr.set_source_rgb(1,0,0)

        self.hitpath = cr.copy_path_flat() #record the path to use as a hit area.
        self.ox,self.oy = cr.get_current_point() 

        cr.fill() #consumes the path, so get it before the fill

    def motion_notify(self,widget,event):
        if self.hit and self.drag:
            self.x, self.y = event.x, event.y
            self.queue_draw()

run(Shapes)

